home *** CD-ROM | disk | FTP | other *** search
/ Lattice ISP Synario Start… & ISP Encyclopedia 1997 / LATTICE Synario.iso / ispcode / source / icode5b.c < prev    next >
Encoding:
Text File  |  1997-08-01  |  31.3 KB  |  685 lines

  1. /****************************************************************************
  2. *                            ispCODE5B.c                                    *
  3. * ispCODE for ispLSI Devices Using the Industry Standard ISP State Machine. *
  4. *              Lattice Semiconductor Corp. Copyright 1996.                  *
  5. *                                                                           *
  6. * ISP(tm) daisy chain turbo programming is supported by ispCODE.            *
  7. *                                                                           *
  8. * The function of this ispCODE is to utilize the Industry Standard ISP state*
  9. * machine in the ispLSI devices for programming and verification. The input *
  10. * file for ispCODE is SLIM ispSTREAM files or Super SLIM ispSTREAM files.   *
  11. *                                                                           *
  12. * The file size of SLIM ispSTREAM is at least 50% less than the FULL        *
  13. * ispSTREAM. The saving comes from stripping out the instructions and field *
  14. * size identifiers. The code size of ispCODE V5.00 for processing the SLIM  *
  15. * ispSTREAM is also reduced by 50% as a result.                             *
  16. *                                                                           *
  17. * The file size of Super SLIM ispSTREAM is about 50% less than the SLIM     *
  18. * ispSTREAM. The extra saving comes from replacing long chain of 0xFFs with *
  19. * the number of consecutive 0xFF bytes. For example:                        *
  20. *           0xFF,0xFF,0xFF,0xC3 is reduced to 0xFF,0x02,0xC3                *
  21. *                                                                           *
  22. * The only restriction on the SLIM ispSTREAM is that the daisy chain must be*
  23. * of the same ISP device types. For example:                                *
  24. *                  A chain of ispGAL22v10 devices.                          *
  25. *                  A chain of ispLSI 1032 devices.                          *
  26. *                  A chain of ispLSI 2032 devices.                          *
  27. *                                                                           *
  28. *                                                                           *
  29. * The SLIM ispSTREAM file is created by the command line program dld2isp.exe*
  30. * v4.02 with the option s selected. For example: type                       *
  31. *                  dld2isp  design.dld s                                    *
  32. * The Super SLIM ispSTREAM file is created by the command line program      *
  33. * dld2isp.exe v4.03 with the option ss selected. For example: type          *
  34. *                  dld2isp  design.dld ss                                   *
  35. *                                                                           *
  36. * The program isp2hex.exe and the source code isp2hex.c can be used to      *
  37. * convert the ispSTREAM file from binary format to C code for linking with  *
  38. * ispcode5.c.                                                               *
  39. *                                                                           *
  40. * All ispLSI devices support the Lattice Semiconductor pioneered UES        *
  41. * feature. If the UES is appended into the JEDEC files using the UES editor *
  42. * on ISP Daisy Chain Download program, the resultant ispSTREAM will take    *
  43. * care of programming and verifying the UES data.                           *
  44. *                                                                            *
  45. * Note: The UES length of most ispLSI devices is the same as their data     *
  46. *       length. If it is found on the data book that they are not the same  *
  47. *       such as ispLSI 3256 and 6192 devices, only the last 160 bits are    *
  48. *       referred to as UES. For example: The data length of ispLSI 3256     *
  49. *       devices is 338 bits and the UES length is 160 bits as shown in the  *
  50. *       data book. Pulse SCLK 338-160=178 times to flush out the phantum    *
  51. *       bits first then read the 1st UES bit.                               *
  52. *                                                                           *
  53. * Revision history:                                                         *
  54. *   5B.000 Howard Tang 06/28/96 Convert from V4.0 to support ISP(tm)          *
  55. *                                programming using the industry standard ISP*
  56. *                                state machine with the SLIM ispSTREAM.     *
  57. *   5B.001 Howard Tang 10/16/96 Add support to Super SLIM ispSTREAM.        *
  58. *   5B.002 Howard Tang 10/21/96 Update the code to support isp2hex.exe      *
  59. *****************************************************************************/
  60.  
  61. #include <stdio.h>
  62. #include <dos.h>
  63. #include <stdlib.h>
  64. #include <string.h>
  65. #include "lattice.h"
  66. #include "istream.hex"
  67.  
  68. /*Global variables */
  69. static unsigned char curch;        /*5B.002 the current data from ispSTREAM*/
  70. unsigned char  *fp;                /*5B.002 pointer to the ispSTREAM*/
  71. static short int  bit=0;           /*the current bit read from ispSTREAM*/
  72.  
  73. static short int inputport=inport1,       /*port address for the input port*/
  74.                  outputport=outport1;      /*port address for the output port*/
  75. static short int isp_pins=NUL;    /*3.02 holds the value of parallel port*/
  76.                                  /*     intialized to drive all pins to LOW*/
  77. /*prototypes*/
  78. void            pulse_width(unsigned short int milliseconds);
  79. void            execute(void);
  80. void            move_to_id_state(void);
  81. short int       ispstream_pump(short int operation, short int *end);
  82. void            error_handler(short int rcode, char *message);
  83. unsigned char   GetByte(void);
  84. void ReadispSTREAMHeader(short int *ChainLength, short int *ErasePulse, 
  85.                          short int *ProgramPulse, short int *RowLength, 
  86.                          unsigned short int *DataSize, 
  87.                          unsigned short int *IDStreamLength);
  88. char ispRead(unsigned short int DataSize, unsigned char *OutData);
  89. void ReadispSTREAMData(unsigned short int DataSize, unsigned char *InData,
  90.                        char SS);
  91. void ispInstruction(short int ChipCount, unsigned char Command);
  92. void ispAddress(short int ChipCount, short int RowLength);
  93. void ispData( unsigned char *InData, unsigned short int DataSize);
  94.  
  95. /***************************************************************************
  96.    Function: isp_setpin(byte pins, byte value)
  97.  
  98.    Purpose:
  99.    To apply the specified value to the pins indicated. This routine will
  100.    likely be modified for specific systems. As an example, this code
  101.    is for the PC, as described below.
  102.  
  103.    This routine uses the IBM-PC standard Parallel port, along with the
  104.    schematic shown in Lattice documentation, to apply the signals to the
  105.    programming loop. 
  106.  
  107.    PC Parallel port pin    Signal name
  108.    --------------------    -----------
  109.          2                   out_SDI
  110.          3                   out_SCLK
  111.          4                   out_MODE
  112.          5                   out_ISP
  113.          6                   out_RESET
  114.          7                   DO5
  115.          8                   out_SENSE_CABLE_OUT    
  116.          9                   DO7
  117.          10                  in_SDO
  118.          12                  in_CABLE_SENSE_IN
  119.          15                  in_VCC_OK 
  120.          20                  GND
  121.  
  122.    Parameters:
  123.          - pins, which is actually a set of bit flags (defined in lattice.h) 
  124.            that correspond to the bits of the data port. Each of the I/O port 
  125.            bits that drives an isp programming pin is assigned a flag 
  126.            (through a #define) corresponding to the signal it drives. To 
  127.            change the value of more than one pin at once, the flags are added 
  128.            together, much like file access flags are.
  129.  
  130.            The bit flags are only set if the pin is to be changed. Bits that 
  131.            do not have their flags set do not have their levels changed. The 
  132.            state of the port is always manintained in the static global 
  133.            variable isp_pins, so that each pin can be addressed individually 
  134.            without disturbing the others.
  135.  
  136.          - value, which is either HIGH (0x01 ) or LOW (0x00 ). Only these two
  137.            values are valid. Any non-zero number sets the pin(s) high.
  138.  
  139.    Returns: nothing.
  140.  
  141.  
  142. **************************************************************************/
  143. void isp_setpin(unsigned char pins, unsigned char value)
  144. {
  145.   /* isp_pins is a Global value that keeps track of the current state
  146.      of the pins  */
  147.  
  148.   if( value ) /* set flagged pins HIGH */
  149.       isp_pins = pins | isp_pins;
  150.   else        /* set flagged pins LOW */
  151.       isp_pins = ~pins & isp_pins;
  152.  
  153.   /* value is put on Parallel port pins */
  154.   outp(outputport, isp_pins);
  155.  
  156. } /* isp_setpin() */
  157.  
  158.  
  159. /***************************************************************************
  160.    Function: isp_SDO()
  161.  
  162.    Purpose:
  163.    To get the value of the SDO pin from the input port.
  164.  
  165.    This routine is specific to the PC parallel port setup, but can easily
  166.    be changed to address each user's hardware.
  167.  
  168.    Parameters: none
  169.  
  170.    Returns: The value of SDO, as a byte, with a value of either 0 or 1.
  171.  
  172.    Notes:
  173.    - This routine uses the I/O port addresses contained in the global
  174.      variable inputport, declared in the lattice.h file. If that
  175.      variable is not set, these routines will not work.
  176.  
  177.  
  178. ****************************************************************************/
  179. unsigned char isp_SDO(void)
  180. {
  181.  /* MUST return either 0x00 or 0x01 */
  182.   return( (unsigned char) ((inp(inputport) & in_SDO ) ? HIGH : LOW) );
  183.  
  184. } /* isp_SDO() */
  185.  
  186. /*************************************************************
  187. *                                                            *
  188. *                         PULSE_WIDTH                        *
  189. * This procedure produce accurate timing only on straight PC *
  190. * DOS. The timing is not guarantee if use on Windows DOS.    *
  191. * The delay() function is available only from BORLAND.       *
  192. *                                                            *
  193. * Users must devise their own timing procedures to ensure    *
  194. * the specified minimum delay is observed when using         *
  195. * different platform.                                        *
  196. *************************************************************/
  197.  
  198.  
  199. void            pulse_width(unsigned short int milliseconds)
  200. {
  201.                 delay(milliseconds);
  202. }
  203.  
  204.  
  205.  
  206. /*************************************************************
  207. *                                                            *
  208. *                      GETBYTE                               *
  209. * This procedure reads a byte from the ispSTREAM.            *
  210. *************************************************************/
  211. unsigned char GetByte()
  212. {
  213.  return (*fp++);
  214. }
  215.  
  216.  
  217. /*************************************************************
  218. *                                                            *
  219. *                      SCLOCK                                *
  220. * This procedure apply a clock to TCK.                       *
  221. *************************************************************/
  222. void sclock(void)
  223. {
  224.  isp_setpin(out_SCLK,HIGH);
  225.  isp_setpin(out_SCLK,LOW);
  226. }
  227.  
  228. /*************************************************************
  229. *                                                            *
  230. *                       SHIFT/EXECUTE                        *
  231. *                                                            *
  232. *************************************************************/
  233. void            execute()
  234. {
  235.    isp_setpin(out_MODE, HIGH);
  236.    isp_setpin(out_SDI, HIGH);
  237.    sclock();
  238.    isp_setpin(out_SDI, LOW);
  239.    isp_setpin(out_MODE, LOW);
  240. }
  241.  
  242.  
  243. /*************************************************************
  244. *                                                            *
  245. *                      MOVE TO ID STATE                      *
  246. *                                                            *
  247. *************************************************************/
  248.  
  249. void            move_to_id_state()
  250. {
  251.    isp_setpin(out_MODE, HIGH);    
  252.    isp_setpin(out_SDI, LOW);   /*extra delay for device to settle*/
  253.    sclock();
  254.    isp_setpin(out_MODE, LOW);
  255. }
  256.  
  257.  
  258. /*************************************************************
  259. *                                                            *
  260. *                     READ_ISPSTREAM_HEADER                  *
  261. * Extract the header from the ispSTREAM file.                *
  262. * Return                                                     *
  263. *     ChainLength--------number of ispLSI devices in the     *
  264. *                        given daisy  chain.                 *
  265. *     ErasePulse---------pulse width in mS for device        *
  266. *                        bulk erase.                         *
  267. *     ProgramPulse-------pulse width in mS for device        *
  268. *                        row by row programming.             *
  269. *     RowLength----------the number of rows of data +UES     *
  270. *     DataSize-----------the size of each row of data        *
  271. *     IDStreamLength-----the bit length of the ID stream.    *
  272. *************************************************************/
  273. void ReadispSTREAMHeader(short int *ChainLength, short int *ErasePulse, 
  274.                          short int *ProgramPulse, short int *RowLength,
  275.                          unsigned short int *DataSize,
  276.                          unsigned short int *IDStreamLength)
  277. {
  278.    
  279.    *ChainLength = GetByte();              
  280.    *ErasePulse = GetByte() * 0x100;
  281.    *ErasePulse += GetByte();
  282.    *ProgramPulse = GetByte(); 
  283.    *RowLength = GetByte() * 0x100;
  284.    *RowLength += GetByte();
  285.    *DataSize = GetByte() * 0x100;
  286.    *DataSize += GetByte();   
  287.    *IDStreamLength = GetByte() * 0x100;
  288.    *IDStreamLength += GetByte();
  289.    /*End of the header of the ispSTREAM file.*/   
  290.    
  291. }
  292.  
  293. /*****************************************************************
  294. *                                                                *
  295. *                     READ_ISPSTREAM_DATA                        *
  296. * Extract the data from the ispSTREAM file.                      *
  297. *     DataSize-----------The number of data bits to be fetched.  *
  298. *     SS-----------------Super SLIM ispSTREAM file if true.      *
  299. * Return                                                         *
  300. *     InData-------------The data stream from ispSTREAM file     *
  301. ******************************************************************/
  302. void ReadispSTREAMData(unsigned short int DataSize, unsigned char *InData, 
  303.                        char SS)
  304. {
  305.  unsigned short int index;
  306.  short  int i,j;
  307.  unsigned char xch;
  308.  static short int FFcount=0; /*5.1*/
  309.  
  310.  j=0;
  311.  xch=0;
  312.  for (index=0; index<DataSize; index++)
  313.      {--bit;
  314.       if (bit<0) 
  315.          {if (FFcount<=0) /*5B.001 Read a new byte if 0xFF chain exhausted*/
  316.              { curch = GetByte(); 
  317.                if ((SS)&&(curch==0xFF)) /*5B.001 Super SLIM ispSTREAM file support*/
  318.                FFcount = GetByte();     /*5B.001 The number of 0xFF bytes*/
  319.              }
  320.           else FFcount--; /*5B.001 Use up the 0xFF chain first*/
  321.           bit=7;
  322.          }
  323.       if ((curch >> bit) & 0x01)  xch |= 0x80 >> index%8;                
  324.       if (index%8==7) {InData[j++] = xch; xch=0;}
  325.      }  
  326.    InData[j] = xch;   /*save the last byte of the current row*/
  327. }
  328.  
  329. /*************************************************************
  330. *                                                            *
  331. *                     ispInstruction                         *
  332. * Send the instruction streams to the devices.               *
  333. *    ChipCount-------The number of devices in the chain.     *
  334. *    Command---------The command to be sent to all devices.  *
  335. *************************************************************/
  336. void ispInstruction(short int ChipCount, unsigned char Command)
  337. {
  338.  char Instruction = 5;       /*All Lattice devices have 5 bit commands*/
  339.  short int index;
  340.  short int i;
  341.  for (index = 0; index < ChipCount; index++) { 
  342.       for (i=0; i<Instruction; i++)
  343.           {isp_setpin(out_SDI, (Command >> i)&0x01); 
  344.            sclock();  /*clock the data into the command registers */
  345.           }
  346.       }
  347. }
  348.  
  349. /*************************************************************
  350. *                                                            *
  351. *                     ispAddress                             *
  352. * Send the Address streams to the devices.                   *
  353. *    ChipCount-------The number of devices in the chain.     *
  354. *    Address---------The full address for the devices.       *
  355. *************************************************************/
  356. void ispAddress(short int ChipCount, short int RowLength)
  357. {
  358.  short int index;
  359.  short int i;
  360.  unsigned short int condition;    /*0x1000 HD devices*/
  361.                                   /*0x2000 HD devices with UES*/
  362.                             /*0x3000 Single row per address HD devices*/
  363.                             /*0x4000 Single row per address HD devices with UES*/
  364.  
  365.  condition = RowLength & 0xF000;
  366.  RowLength = RowLength & 0x0FFF;      /*Mask out the condition bits*/  
  367.  if ((condition==0x2000)||(condition==0x4000)) 
  368.     RowLength = (RowLength-1)/2;      /*Exclude the UES row from address*/
  369.  else if ((condition==0x1000)||(condition==0x3000))
  370.     RowLength = RowLength/2;          /*High Low Order addressing*/
  371.  
  372.  for (index = 0; index < ChipCount; index++) { 
  373.       for (i=1; i<RowLength; i++)
  374.            sclock();  /*clock  zeros into the address registers */
  375.       isp_setpin(out_SDI,HIGH);
  376.       sclock();       /*clock a one into the address registers*/
  377.       isp_setpin(out_SDI,LOW);
  378.       }
  379.  execute();   /*step to shift state*/ 
  380. }
  381.  
  382. /**********************************************************************
  383. *                                                                     *
  384. *                     ispData                                         *
  385. * Send the data stream to devices.                                    *
  386. *    InData-----------The data stream to be sent to devices.          *
  387. *    DataSize---------The length of the data stream.                  *
  388. ***********************************************************************/
  389. void ispData(unsigned char *InData, unsigned short int DataSize)
  390. {
  391.  unsigned short int index;
  392.  short int i,j;
  393.  unsigned char xch;
  394.  
  395.  j=0;
  396.  for (index = 0; index <DataSize; index++) { 
  397.       if (index%8==0) xch = InData[j++];
  398.       isp_setpin(out_SDI, (((xch << index%8) & 0x80) ? 0x01 : 0x00)); 
  399.       sclock();  /*clock data into the data shift registers */
  400.       }
  401.  execute();   /*step to shift state*/ 
  402. }
  403.  
  404. /**********************************************************************
  405. *                                                                     *
  406. *                     ispRead                                         *
  407. * Read the data stream from devices and verify.                       *
  408. *    DataSize---------The length of the data stream.                  *
  409. *    OutData----------The data stream to be compare with those read   *
  410. *                     from devices.                                   *
  411. ***********************************************************************/
  412. char ispRead(unsigned short int DataSize, unsigned char *OutData)
  413. {
  414.  unsigned short int index,error;
  415.  short int i,j;
  416.  unsigned char xch,cur_bit;
  417.  
  418.  j=0;
  419.  error=0;
  420.  xch=0;
  421.  for (index = 0; index <DataSize; index++) { 
  422.       if (index%8==0) xch = OutData[j++];
  423.       cur_bit=isp_SDO(); 
  424.       if (cur_bit != (((xch << index%8) & 0x80) ? 0x01 : 0x00)) error++;  
  425.       sclock();  /*clock data out from the data shift registers */
  426.       }
  427.  execute();   /*step to shift state*/ 
  428.  if (error > 0) return 1;      /*Flag failure occur*/
  429.  else return (0);
  430. }
  431.  
  432. /*************************************************************
  433. *                                                            *
  434. *                     ISPSTREAM_PUMP                         *
  435. *                                                            *
  436. *************************************************************/
  437.  
  438. short int   ispstream_pump(short int operation, short int *end)
  439. {
  440.    short int       row;
  441.    short int       HDDevices,HighLow;     /*device types identifiers*/  
  442.    char            SS;                    /*ispSTREAM file types identifier*/
  443.    unsigned char   Command,UES,FileType;
  444.    short int       last_row,
  445.                    erase_pulse,
  446.                    program_pulse,
  447.                    devices_in_chain;
  448.    unsigned short int    maxi_data,
  449.                          data_length,
  450.                             id_length;
  451.    short int       rcode;
  452.    short int       DeviceType,EndRow;
  453.    unsigned char   *buf;
  454.  
  455.    row =0;
  456.    bit = 0;
  457.    /*Start reading the header of the ispSTREAM file*/
  458.    fp = ispstream;
  459.    FileType = GetByte();
  460.    if (FileType == 0x00) {SS=false;}          /*Check for correct file type*/
  461.    else if (FileType == 0x02 ) {SS=true;}     /*Super SLIM ispSTREAM file found*/ 
  462.    else {
  463.         return FILE_NOT_JEDEC;
  464.        }
  465.    ReadispSTREAMHeader(&devices_in_chain, &erase_pulse, &program_pulse,
  466.                            &last_row, &maxi_data, &id_length);
  467.  
  468.    rcode = OK;                                /*Success by default.*/
  469.    DeviceType = last_row & 0xF000;            /*Device types code*/
  470.    EndRow = last_row & 0x0FFF;                /*Actual address length*/
  471.    if (DeviceType >= 0x1000)  
  472.        HDDevices = true;                    /*ispLSI devices found*/
  473.    else HDDevices = false;                 /*ispGAL or ispGDS found*/
  474.    if ((DeviceType == 0x1000) || (DeviceType == 0x2000))
  475.       HighLow = true;                       /*Devices need High/Low addressing  detected*/
  476.    else HighLow = false; 
  477.    if ((DeviceType==0x2000)||(DeviceType==0x4000))
  478.       UES=true;                             /*UES programming required*/
  479.    else UES=false;
  480.    if ((operation==verify)||(operation==verify_ues))    /*verify only*/
  481.       {erase_pulse=0;                       /*void the erase instruction*/ 
  482.        program_pulse=0;                     /*void the program instruction*/
  483.       }
  484.    if ((operation==verify_ues)&&(!UES))     /*The ispSTREAM has no UES*/
  485.       return FILE_NOT_JEDEC;
  486.    
  487.    /*Allocate memory to store one row of data from the ispSTREAM file.*/
  488.    buf = buffer;
  489.    isp_pins = NUL;          /* intialize to drive all port pins LOW*/
  490.    isp_setpin(out_ISP, LOW);/* drive ispEN pin low to enable the 
  491.                                    ISP controlling pins:
  492.                                    SCLK,MODE,SDI and SDO.*/ 
  493.    move_to_id_state();                      /*Initialise the devices*/
  494.    execute();                               /*Synchronize the devices*/
  495.    move_to_id_state();                      /*Load the IDs*/
  496.    ReadispSTREAMData(id_length,buf,SS);      /*fetch ID stream from ispSTREAM*/
  497.    rcode = ispRead(id_length,buf);          /*verify the ID stream*/    
  498.    if (rcode != OK)     
  499.        return UNKNOWN_CHIP;      
  500.    if (erase_pulse > 0)                         /*erase the devices*/
  501.       {
  502.        if (HDDevices) Command = ERASE_ALL;
  503.        else Command = ERASE;
  504.        ispInstruction(devices_in_chain,Command);   
  505.        execute();                               /*step to execute state*/
  506.        sclock();                                /*start the erase timing*/
  507.        pulse_width(erase_pulse);                /*erase pulse*/
  508.        isp_setpin(out_MODE, HIGH);
  509.        isp_setpin(out_SDI,HIGH);
  510.        pulse_width(1);                          /*super voltage discharge*/
  511.        sclock();
  512.        isp_setpin(out_SDI,LOW);
  513.        isp_setpin(out_MODE,LOW);                /*devices in shift state*/
  514.       }
  515.    if (operation==verify_ues)                   /*verify ues only*/
  516.       {for (row=1; row<EndRow; row++)          /*skip array data */
  517.            {
  518.             if ((HDDevices)&&(!HighLow)&&(row%2==0))/*single address per row HD devices*/
  519.                {}                                   /*devices have no Low Order rows*/
  520.             else
  521.                ReadispSTREAMData(maxi_data,buf,SS); /*fetch and trash ispSTREAM*/
  522.            }
  523.        }
  524.    else row =1;       
  525.  
  526.  
  527.    /*start processing the rows in the ispSTREAM file*/
  528.  
  529.    for (; row <= EndRow; row++) {
  530.       *end = row;                               /* The row number where process ended.*/
  531.        if ((HDDevices)&&(!HighLow)&&(row%2==0))/*single address per row HD devices*/
  532.           {}                                    /*devices have no Low Order rows*/
  533.        else {                                   
  534.              if ((HDDevices)&&(row%2==1))       /* Addressing for ispLSI devices*/
  535.                 {
  536.                  ispInstruction(devices_in_chain,SHIFT_ADDRESS);
  537.                  execute();                           /*step to execute state*/
  538.                  if (row==1)                          /* Full addressing once*/ 
  539.                     ispAddress(devices_in_chain,last_row);  
  540.                  else {sclock(); execute();}          /*shift to next address*/
  541.                  }             
  542.             if ((!HDDevices)&&(row==45))        /*fetch ispGAL22v10 ARCH row*/
  543.                data_length = 20*devices_in_chain;
  544.             else data_length = maxi_data;
  545.             ReadispSTREAMData(data_length,buf,SS); /*fetch data stream from ispSTREAM*/
  546.             if ((!HDDevices)&&(row==45))        /*ispGAL22v10 ARCH row*/
  547.                 Command = ARCH_SHIFT;
  548.             else Command = SHIFT_DATA;
  549.             ispInstruction(devices_in_chain,Command);
  550.             execute();                          /*step to execute state*/
  551.             ispData(buf,data_length);         /*send data into devices*/
  552.             if (program_pulse > 0)               /*program and verify*/
  553.                {
  554.                 if ((HighLow)&&(row%2==0))      /*Low Order rows*/
  555.                    Command = PROGRAM_LOW;
  556.                 else Command = PROGRAM_HIGH;
  557.                 if ((UES)&&(row==EndRow)) Command = PROGRAM_UES;
  558.                 ispInstruction(devices_in_chain,Command);
  559.                 execute();                      /*step to execute state*/
  560.                 sclock();                       /*start program timing*/
  561.                 pulse_width(program_pulse);
  562.                 execute();                      /*step to shift state*/
  563.                } 
  564.             if ((HighLow)&&(row%2==0))          /*Low Order rows*/
  565.                 Command = VERIFY_LOW_PROG;
  566.             else Command = VERIFY_HIGH_PROG;
  567.             if ((UES)&&(row==EndRow)) Command = VERIFY_UES;
  568.             ispInstruction(devices_in_chain,Command);
  569.             execute();                          /*step to execute state*/
  570.             sclock();                           /*start verify timing*/
  571.             pulse_width(1);                     /*30uS min. verify time*/
  572.             execute();                          /*step to shift state*/
  573.             if ((!HDDevices)&&(row==45))        /*ispGAL22v10 ARCH row*/
  574.                Command = ARCH_SHIFT;
  575.             else Command = SHIFT_DATA;
  576.             ispInstruction(devices_in_chain,Command);
  577.             execute();                          /*step to execute state*/
  578.             rcode = ispRead(data_length,buf);   /*verify the data stream*/
  579.             if (rcode != OK)  break;
  580.            }
  581.       }        
  582.    move_to_id_state();                          /*activate ispGAL and ispGDS*/
  583.    isp_setpin(out_ISP,HIGH);                    /*activate ispLSI devices*/
  584.    if (rcode==OK) return (OK);
  585.    else return VALIDATION_ERROR;      
  586.  
  587. }
  588.  
  589. /*************************************************************
  590. *                                                            *
  591. *                         error_handler                      *
  592. *                                                            *
  593. *  rcode                  - error code                       *
  594. *                                                            *
  595. *                                                            *
  596. *  This procedure return the address of the message string   *
  597. *  for the corresponding error code.                         *
  598. *                                                            *
  599. *************************************************************/
  600.  
  601. void error_handler(short int rcode, char *message)
  602. {
  603.  
  604. char *error_message[] = {{"PASS"},{""},{""},{"PC Hardware Problem"},{""},
  605.                    {""},{""},
  606.                    {"No Device Found/Open Download Cable/Open Daisy Chain"},
  607.                    {"Can't Find the File"},{""},{"Not Enough PC Memory"},
  608.                    {"Verification Fail"},{""},{""},
  609.                    {""},
  610.                    {"The Chip Count in the Chain and the File Do Not Match"},
  611.                    {"Unknown Device Found"},{"Wrong File Type"},{"File Error"},
  612.                    {""}};
  613.  
  614.  strcpy(message, error_message[-rcode]);
  615.  
  616.  
  617.  
  618. /*************************************************************
  619. *                                                            *
  620. *                            MAIN                            *
  621. *                                                            *
  622. *************************************************************/
  623.  
  624. short int          main(int argc, char *argv[])
  625. {
  626.    short int       rcode = OK,
  627.                    end = 0;
  628.    char            str[300];
  629.    short int operation=prog_verify;  /*3.05 Default to Program and Verify*/
  630.    
  631.    printf("\n                 Lattice Semiconductor Corp.\n");
  632.    printf("\n              ispCODE V5B.002 Copyright 1996,1997.\n");
  633.    printf("\n           SLIM ispSTREAM Driver for ispLSI Devices\n");
  634.    printf("\n For Simple Daisy Chain of The Same Device Type On LSC ISP Controller\n\n");
  635.  
  636.    if ((argc < 1) || (argc > 2)) {
  637.       printf("\nUsage: sturbo [operation]\n");
  638.       printf("Example: sturbo pv\n");
  639.       printf("\n");
  640.       printf("operation            \"pv\" = program and verify\n");
  641.       printf("                     \"v\" = Verify only\n");
  642.       printf("                     \"uv\" = Verify UES only\n");
  643.       printf("                     Default to pv if operation is not entered.\n");                            
  644.       exit(1);
  645.    }
  646.  
  647.    /*3.02 set the initial condition of the parallel port*/
  648.    /*     All the port_pins defined on lattice.h will be controlled by
  649.           ispstream_pump(). The rest can be initialized here either to
  650.           HIGH or LOW and won't be altered by isptream_pump*/
  651.             
  652.       if (rcode == OK){        /*start programming and verification*/
  653.                 
  654.           if(!strcmp(strlwr(argv[1]),"uv")){                  /*3.05 What to do? uv=ues verify only*/
  655.               operation=verify_ues;                                      /*for verify ues only =1*/  
  656.               printf("\nStart Verify UES of ispLSI devices.......\n");}  
  657.           else if(!strcmp(strlwr(argv[1]),"v")){               /*v = verify only*/
  658.               operation=verify;
  659.               printf("\nStart Verify.......\n");}
  660.           else {                                               /*pv = program and verify: Default*/
  661.                   operation=prog_verify;
  662.                   printf("\nStart Program and Verify.......\n");
  663.                }    
  664.  
  665.    rcode = ispstream_pump(operation, &end);       /*3.05 add operation switch*/
  666.        }
  667.    if (rcode != OK) {
  668.       error_handler(rcode, str);
  669.       printf("\nFailed At Row %d in Program and Verify Due To %s\n", end, str);
  670.       printf("\n");
  671.       printf("+-------+\n");
  672.       printf("| FAIL! |\n");
  673.       printf("+-------+\n");
  674.       return (-rcode);
  675.    } else {
  676.       printf("\n");
  677.       printf("+=======+\n");
  678.       printf("| PASS! |\n");
  679.       printf("+=======+\n");
  680.    }
  681.  
  682.    return(0);
  683.